package SwingView.Quiz;

import JDBC.StudentQuizActivities;
import SwingModel.CmsQuiz;
import SwingModel.CmsQuizQuestion;
import SwingModel.CmsQuizSubmission;
import SwingView.CmsContentPanelModel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jdesktop.swingx.JXDatePicker;

import SwingController.ALDownloadFile;
import SwingController.CmsPresenter;
import SwingModel.CmsAssignment;
import SwingView.CmsContentPanelModel;
import SwingView.CmsTimeSelector;


public class CmsCPQuizTake extends CmsContentPanelModel {
	
	private CmsQuiz quiz;
	final private static DecimalFormat decimalFormat = new DecimalFormat("00");

	private final JPanel jpContent;
	private JTextArea jtfTitle;
	private JTextArea jtfDescription;
	private JProgressBar jpbRemainTime;
	private JButton jbtSubmit;
	private List<QuestionPanel4Take> listOfQuestionPanel;
	
	private CmsAssignment asgm;
	private JTextArea jtfDueDate;
	private JTextArea jtfWeight;
	private JPanel jpQuestions;


	private JTextArea jtfTime;


	private JTextArea jtfNumQuestion;
	private QuizTime quizTime;
	private Timer progressTimer;
	private Timer submitTimer;
	
	public CmsCPQuizTake(){
		listOfQuestionPanel = new ArrayList();
		
		//helper panel to center the title panel
		JPanel jp = new JPanel();
		jp.setOpaque(false);
		jp.setPreferredSize(new Dimension(650, 65));
		jp.setBorder(BorderFactory.createEmptyBorder());
		GridBagLayout gbl_jp = new GridBagLayout();
		jp.setLayout(gbl_jp);
		
		//content panel
		jpContent = new JPanel();
		GridBagLayout gbl_jpContent = new GridBagLayout();
		jpContent.setLayout(gbl_jpContent);
		jpContent.setOpaque(false);

		//Set up the scroll bar
		JScrollPane scroll = new JScrollPane(jpContent);
		
		//main Scroll bar
		scroll.setBorder(BorderFactory.createEmptyBorder());
		scroll.setOpaque(true);
		scroll.setPreferredSize(new Dimension(650,450));
		scroll.setBackground(Color.WHITE);

		//set up main panel and add components
		setLayout(new BorderLayout());
		setOpaque(false);
		add(jp,BorderLayout.NORTH);//Add title People
		
		//instantiate Quiz title
		JLabel jlAsgmComposerTitle = new JLabel("Quiz");
		jlAsgmComposerTitle.setFont(jlAsgmComposerTitle.getFont().deriveFont(20.0f).deriveFont(Font.BOLD));
		jlAsgmComposerTitle.setBorder(BorderFactory.createEmptyBorder(0, 8, 10, 8));
		GridBagConstraints gbc_jlQuizComposerTitle = new GridBagConstraints();
		gbc_jlQuizComposerTitle.gridwidth = 2;
		gbc_jlQuizComposerTitle.gridx = 0;
		gbc_jlQuizComposerTitle.gridy = 0;
		jp.add(jlAsgmComposerTitle, gbc_jlQuizComposerTitle);
		
		jpbRemainTime = new JProgressBar();
		jpbRemainTime.setFont(jpbRemainTime.getFont().deriveFont(Font.BOLD).deriveFont(13.0f));
		jpbRemainTime.setPreferredSize(new Dimension(200, 20));
		jpbRemainTime.setMinimumSize(new Dimension(200,20));
		jpbRemainTime.setStringPainted(true);
		jpbRemainTime.setBorder(BorderFactory.createLineBorder(new Color(30,30,30)));
		GridBagConstraints gbc_jbtClear = new GridBagConstraints();
		gbc_jbtClear.insets = new Insets(0, 0, 0, 20);
		gbc_jbtClear.gridx = 0;
		gbc_jbtClear.gridy = 1;
		jp.add(jpbRemainTime, gbc_jbtClear);
		
		jbtSubmit = new JButton("Submit");
		jbtSubmit.setFont(jbtSubmit.getFont().deriveFont(Font.BOLD).deriveFont(13.0f));
		jbtSubmit.setPreferredSize(new Dimension(70, 20));
		jbtSubmit.setMinimumSize(new Dimension(75,20));
		jbtSubmit.setBackground(new Color(170,170,170));
		jbtSubmit.setForeground(new Color(30,30,30));
		jbtSubmit.setOpaque(true);
		jbtSubmit.setBorder(BorderFactory.createLineBorder(new Color(30,30,30)));
		GridBagConstraints gbc_jbtPost = new GridBagConstraints();
		gbc_jbtPost.insets = new Insets(0, 20, 0, 0);
		gbc_jbtPost.gridx = 1;
		gbc_jbtPost.gridy = 1;
		jp.add(jbtSubmit, gbc_jbtPost);
		add(scroll,BorderLayout.WEST);//Add People List
		
		//_________________________________________________________
		//TITLE:
		
		JLabel jlTitle = new JLabel("Title: ");
		jlTitle.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_jlTitle = new GridBagConstraints();
		gbc_jlTitle.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jlTitle.insets = new Insets(0, 40, 5, 5);
		gbc_jlTitle.gridx = 0;
		gbc_jlTitle.gridy = 0;
		jpContent.add(jlTitle, gbc_jlTitle);
		
		jtfTitle = new JTextArea();
		jtfTitle.setToolTipText("Please enter the assignment title");
		jtfTitle.setBorder(BorderFactory.createEmptyBorder());
		GridBagConstraints gbc_jtfTitle = new GridBagConstraints();
		gbc_jtfTitle.insets = new Insets(0, 0, 5, 40);
		gbc_jtfTitle.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jtfTitle.weightx = 1.0;
		gbc_jtfTitle.gridx = 1;
		gbc_jtfTitle.gridy = 0;
		gbc_jtfTitle.fill = GridBagConstraints.HORIZONTAL;
		jpContent.add(jtfTitle, gbc_jtfTitle);
		
		//_________________________________________________________
		//DESCRIPTION:

		
		JLabel jlDescription = new JLabel("Description: ");
		jlDescription.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_jlDescription = new GridBagConstraints();
		gbc_jlDescription.insets = new Insets(0, 40, 5, 5);
		gbc_jlDescription.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jlDescription.gridx = 0;
		gbc_jlDescription.gridy = 1;
		jpContent.add(jlDescription, gbc_jlDescription);
		
		jtfDescription = new JTextArea();
		jtfDescription.setLineWrap(true);
		jtfDescription.setWrapStyleWord(true);
		GridBagConstraints gbc_jspDescription = new GridBagConstraints();
		gbc_jspDescription.insets = new Insets(0, 0, 30, 40);
		gbc_jspDescription.fill = GridBagConstraints.HORIZONTAL;
		gbc_jspDescription.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jspDescription.gridx = 1;
		gbc_jspDescription.gridy = 1;
		gbc_jspDescription.weightx = 1.0;
		jpContent.add(jtfDescription, gbc_jspDescription);
		
		//_________________________________________________________
		//DUE DATE:
		JLabel lblDueDate = new JLabel("Due Date:");
		lblDueDate.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblDueDate = new GridBagConstraints();
		gbc_lblDueDate.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblDueDate.insets = new Insets(0, 40, 5, 5);
		gbc_lblDueDate.gridx = 0;
		gbc_lblDueDate.gridy = 2;
		jpContent.add(lblDueDate, gbc_lblDueDate);
		
		jtfDueDate = new JTextArea();
		GridBagConstraints gbc_jtfDueDate = new GridBagConstraints();
		gbc_jtfDueDate.insets = new Insets(0, 0, 5, 40);
		gbc_jtfDueDate.fill = GridBagConstraints.BOTH;
		gbc_jtfDueDate.gridx = 1;
		gbc_jtfDueDate.gridy = 2;
		jpContent.add(jtfDueDate, gbc_jtfDueDate);
		
		JLabel lblTimeConstraint = new JLabel("Time Constraint: ");
		lblTimeConstraint.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblTimeConstraint = new GridBagConstraints();
		gbc_lblTimeConstraint.anchor = GridBagConstraints.LINE_START;
		gbc_lblTimeConstraint.insets = new Insets(0, 40, 5, 5);
		gbc_lblTimeConstraint.gridx = 0;
		gbc_lblTimeConstraint.gridy = 3;
		jpContent.add(lblTimeConstraint, gbc_lblTimeConstraint);
		
		jtfTime = new JTextArea();
		GridBagConstraints gbc_jtfTime = new GridBagConstraints();
		gbc_jtfTime.insets = new Insets(0, 0, 5, 40);
		gbc_jtfTime.fill = GridBagConstraints.BOTH;
		gbc_jtfTime.gridx = 1;
		gbc_jtfTime.gridy = 3;
		jpContent.add(jtfTime, gbc_jtfTime);
		
		JLabel lblOfQuestions = new JLabel("# of Questions");
		lblOfQuestions.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblOfQuestions = new GridBagConstraints();
		gbc_lblOfQuestions.insets = new Insets(0, 40, 5, 5);
		gbc_lblOfQuestions.gridx = 0;
		gbc_lblOfQuestions.gridy = 4;
		jpContent.add(lblOfQuestions, gbc_lblOfQuestions);
		
		jtfNumQuestion = new JTextArea();
		GridBagConstraints gbc_jtfNumQuestion = new GridBagConstraints();
		gbc_jtfNumQuestion.insets = new Insets(0, 0, 5, 40);
		gbc_jtfNumQuestion.fill = GridBagConstraints.BOTH;
		gbc_jtfNumQuestion.gridx = 1;
		gbc_jtfNumQuestion.gridy = 4;
		jpContent.add(jtfNumQuestion, gbc_jtfNumQuestion);
		
		JLabel jlWeight = new JLabel("Percent Weight: ");
		GridBagConstraints gbc_jlWeight = new GridBagConstraints();
		gbc_jlWeight.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jlWeight.insets = new Insets(0, 40, 5, 5);
		gbc_jlWeight.gridx = 0;
		gbc_jlWeight.gridy = 5;
		jpContent.add(jlWeight, gbc_jlWeight);
		jlWeight.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		
		jtfWeight = new JTextArea();
		GridBagConstraints gbc_jtfWeight = new GridBagConstraints();
		gbc_jtfWeight.anchor = GridBagConstraints.LINE_START;
		gbc_jtfWeight.insets = new Insets(0, 0, 30, 40);
		gbc_jtfWeight.fill = GridBagConstraints.BOTH;
		gbc_jtfWeight.gridx = 1;
		gbc_jtfWeight.gridy = 5;
		jpContent.add(jtfWeight, gbc_jtfWeight);
		
		//Files Label
		JLabel lblFiles = new JLabel("Quiz Questions:");
		GridBagConstraints gbc_lblFiles = new GridBagConstraints();
		gbc_lblFiles.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_lblFiles.insets = new Insets(0, 40, 5, 5);
		gbc_lblFiles.gridx = 0;
		gbc_lblFiles.gridy = 6;
		jpContent.add(lblFiles, gbc_lblFiles);
		lblFiles.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		
		jpQuestions = new JPanel(new GridBagLayout());
		jpQuestions.setOpaque(false);
		GridBagConstraints gbc_jpQuestions = new GridBagConstraints();
		gbc_jpQuestions.insets = new Insets(10, 40, 10, 40);
		gbc_jpQuestions.gridwidth = 2;
		gbc_jpQuestions.weighty = 1.0;
		gbc_jpQuestions.fill = GridBagConstraints.BOTH;
		gbc_jpQuestions.gridx = 0;
		gbc_jpQuestions.gridy = 7;
		jpContent.add(jpQuestions, gbc_jpQuestions);
		
		
	}
	
	public void displayListOfQuestion(){
		jpQuestions.removeAll();
		for(int i=0; i < listOfQuestionPanel.size(); i++){
			GridBagConstraints c = new GridBagConstraints();
			c.gridy = i;
			c.insets = new Insets(0,0,10,0);
			c.anchor = GridBagConstraints.FIRST_LINE_START;
			c.fill = GridBagConstraints.HORIZONTAL;
			jpQuestions.add(listOfQuestionPanel.get(i),c); //add to panel for displaying
			System.out.println(i);
		}
		
		//empty space at bottom - used to fill the bottom of the page
		//when the list is too short
		JPanel p = new JPanel();
		p.setOpaque(false);
		p.setBackground(Color.WHITE);
		GridBagConstraints c_p = new GridBagConstraints();
		c_p.gridy = listOfQuestionPanel.size();
		c_p.fill = GridBagConstraints.VERTICAL;
		c_p.weightx=1.0;
		c_p.weighty=1.0;
		jpQuestions.add(p,c_p);
		
		jpQuestions.revalidate();
				
		jpQuestions.revalidate();
	}
	
	public void loadQuiz(CmsQuiz quiz){
		this.quiz = quiz;
		resetAllField();
	}
	
	public void resetAllField(){
		
		if(quiz != null){
			this.jtfTitle.setText(quiz.getQuizTitle());
			this.jtfDescription.setText(quiz.getQuizDescription());
			
			//display dueDate
			this.jtfDueDate.setText(CmsPresenter.sdf.format(new Date(quiz.getDueDate().getTime())));
			
			//display time constraint
			if(quiz.getDuration() == 0){
				jtfTime.setText("<NONE>");
			}
			else this.jtfTime.setText("" + quiz.getDuration() + " minutes");
			
			this.jtfNumQuestion.setText("" + quiz.getMaxPoint() + " questions");
			this.jtfWeight.setText("" + quiz.getPercentWeight() + "%");
			
			int questionIndex = 1;
			listOfQuestionPanel = new ArrayList();
			displayListOfQuestion();
			
			for(CmsQuizQuestion question : quiz.getQuestions()){
				listOfQuestionPanel.add(new QuestionPanel4Take(question,questionIndex++));
			}
			
			//Start timer
			int duration = quiz.getDuration();
			
			displayListOfQuestion();			
			
			if(duration > 0){ //there is time constraint
				this.quizTime = new QuizTime(duration);
				jpbRemainTime.setString("Remaining Time: " + decimalFormat.format(quizTime.min) + ":" + decimalFormat.format(quizTime.sec));
				jpbRemainTime.setMinimum(0);
				jpbRemainTime.setMaximum(duration * 60);
				jpbRemainTime.setValue(0);
				progressTimer = new Timer(1000, new UpdateTimeListener());
				progressTimer.start();
				submitTimer = new Timer(duration*60*1000, new TimerSubmitQuizListener());
				submitTimer.start();
			}
			else{ // no time constraint
				jpbRemainTime.setString("No Time Limit");
			}
			
			jbtSubmit.addActionListener(new ButtonSubmitQuizListener());
			
		}
		else{
			JOptionPane.showMessageDialog(CmsPresenter.mainView, "ERROR: Could not find the quiz you want to take! ", "ERROR", JOptionPane.ERROR_MESSAGE);
			CmsPresenter.mainView.displayQuizStudentPage(StudentQuizActivities.getListOfQuiz(CmsPresenter.user.getSelectedCourse().getCourseID()));
		}
		
		
		//TODO: add actionlistener for submission and edit
		
		
		System.out.println("DISPLAY THIS QUIZ FOR VIEW:\n" + quiz);
	}
	

	
	public CmsQuizSubmission getStudentSubmission(){
		String studentID = CmsPresenter.user.getUsername();
		int quizID = quiz.getQuizID();
		char[] answer = new char[listOfQuestionPanel.size()];
		double givenPoint = 0;
		
		for (int i = 0; i < answer.length; i++){
			answer[i] = listOfQuestionPanel.get(i).getStudentSelectedOption();
		}
		
		for( QuestionPanel4Take questionP : listOfQuestionPanel){
			if(questionP.getStudentSelectedOption() == questionP.getKey()) givenPoint++;
		}
		
		givenPoint = givenPoint/listOfQuestionPanel.size() * 100.0d;
		
		return new CmsQuizSubmission(studentID, quizID, answer, givenPoint);
	}
	
	class QuizTime {
		public int min;
		public int sec;

		QuizTime(int min){
			this.min = min;
			this.sec = 0;
		}
		
		public void countDown(){
			if(this.sec == 0){
				sec = 59;
				min--;
			}
			else{
				sec--;
			}
		}
		
		public boolean timeUp(){
			if(sec == 0 && min == 0){
				return true;
			}
			else return false;
		}
	}
	
	class TimerSubmitQuizListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			StudentQuizActivities.submitQuiz(getStudentSubmission());
			CmsPresenter.mainView.displayQuizStudentPage(StudentQuizActivities.getListOfQuiz(CmsPresenter.user.getSelectedCourse().getCourseID()));
			JOptionPane.showMessageDialog(CmsPresenter.mainView, "TIME UP!\nYour quiz was submitted automatically.");
			submitTimer.stop();
		}
		
	}
	
	class ButtonSubmitQuizListener implements ActionListener{
		@Override
		public void actionPerformed(ActionEvent e) {
			//CHECK IF STUDENT MISSING ANY QUESTION
			StringBuilder message = new StringBuilder("You did not provide answer for the following question numbers:\n\n     - ");
			boolean result = true;
			int index = 1;
			for(QuestionPanel4Take qP : listOfQuestionPanel){
				if(qP.getStudentSelectedOption() == '0'){
					result = false;
					message.append(" " + index + ",");
				}
				index++;
			}
			
			if(result == false){
				int userConfirm = userConfirm = JOptionPane.showConfirmDialog(CmsPresenter.mainView, message, "WARNING", JOptionPane.WARNING_MESSAGE);
				if(userConfirm == JOptionPane.YES_OPTION){
					StudentQuizActivities.submitQuiz(getStudentSubmission());
					CmsPresenter.mainView.displayQuizStudentPage(StudentQuizActivities.getListOfQuiz(CmsPresenter.user.getSelectedCourse().getCourseID()));
					if(submitTimer != null && progressTimer != null){
						submitTimer.stop();
						progressTimer.stop();
					}
				}
			}
			else {
				
				int userConfirm = JOptionPane.showConfirmDialog(CmsPresenter.mainView, "Do you want to submit your quiz?");
				if(userConfirm == JOptionPane.YES_OPTION){
					StudentQuizActivities.submitQuiz(getStudentSubmission());
					CmsPresenter.mainView.displayQuizStudentPage(StudentQuizActivities.getListOfQuiz(CmsPresenter.user.getSelectedCourse().getCourseID()));
					//CmsPresenter.mainView.displayQuizResultPage(quiz, StudentQuizActivities.getQuizSubmission(quiz.getQuizID(), CmsPresenter.user.getUsername()));
					if(submitTimer != null && progressTimer != null){
						submitTimer.stop();
						progressTimer.stop();
					}
					
				}
			}
			
		}
	}
	
	
	class UpdateTimeListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			if(!quizTime.timeUp()){
				quizTime.countDown();
				
				int curValue = jpbRemainTime.getValue();
				jpbRemainTime.setValue(++curValue);
				
				jpbRemainTime.setString("Remaining Time: " + decimalFormat.format(quizTime.min) + ":" + decimalFormat.format(quizTime.sec));
			}
			else{
				jpbRemainTime.setValue(quiz.getDuration());
				jpbRemainTime.setString("Time Up!");
				progressTimer.stop();
			}
		}
		
	}
}
